home *** CD-ROM | disk | FTP | other *** search
/ Turnbull China Bikeride / Turnbull China Bikeride - Disc 2.iso / STUTTGART / UNIXTOOL / MANSRC / _files / _mansrc / man_c next >
Encoding:
Text File  |  1991-06-28  |  15.4 KB  |  505 lines

  1.  
  2. /*------------------------------------------------------------------------*
  3.  * Title   : c.man
  4.  * Purpose : Manual page find utility
  5.  *           allows searching via index, page filename, volume, wildcards
  6.  *           and by content.
  7.  * History : 10:57 20-Dec-90 Created. 
  8.  *           19:40 completed.
  9.  *           23:40 Added -k option.
  10.  *           10:30 21-Dec-90 Fixed bug with search_index
  11.  *                 It didn't read every Name entry, skipped some.
  12.  *------------------------------------------------------------------------*/
  13.  
  14.  
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <string.h>
  18. #include <ctype.h>
  19. #include <signal.h>
  20. #include <kernel.h> 
  21.  
  22. #define CHK(p) ((p)?p:"NULL")
  23. #define FALSE 0
  24. #define TRUE (!FALSE)
  25.  
  26. extern int wildmat(char *,char *);
  27. extern int search_index(char *);
  28. extern void search_page(char *);
  29. extern void vol_scan(const char *,char *);
  30. extern void escape(int );
  31. extern void syntax(const char *);
  32. extern char *read_sys_var(const char *);
  33.  
  34. char *version="1.01";
  35. char *root_dir=NULL;
  36. char *keyword=NULL, *search=NULL, *volume=NULL, *page=NULL, *com=NULL;
  37. int  index=0,found=0,nk=0;
  38.  
  39. #if defined(MY_WILDCARD_ROUTINE)
  40. /* ------------------------ wildmat ------------------------------------
  41.  * Purpose    : given a wildcarded string and a string, determines 
  42.  *              whether a match exists between the two.
  43.  * Paramaters : pointer to wildcarded string
  44.  *              pointer to string
  45.  * Returns    : 0 if no match,
  46.  *              1 if matched.
  47.  */
  48.  
  49. int wildmat(char *s,char *wcs)
  50. {
  51.   int i,j=0;
  52.   for (i=0; i<strlen(s); i++)   /* going through string serially */
  53.   {
  54.     if ( (wcs[j]=='\0') && (s[i+1]!='\0') ) return 0;
  55.     if (wcs[j]=='*')            /* A * can replace 0 or more chars */
  56.     {
  57.       while (wcs[j]=='*') j++; /* gets rid of double *'s */
  58.       while (s[i])
  59.       { /* First find the occurance of the character after the wildcard
  60.          * in the string. Note: & 0xDF to convert lowercase to uppercase.
  61.          */
  62.         if ((s[i] & 0xDF) != (wcs[j] & 0xDF) ) i++; 
  63.         else 
  64.           if ( (s[i+1] & 0xDF) == (s[i] & 0xDF) )
  65.           { /* find last character in sequence of same chars */
  66.             i++;
  67.             continue; 
  68.           }
  69.           else break;
  70.       }
  71.     }
  72.     if ((wcs[j] & 0xDF) == (s[i] & 0xDF)) j++; else return 0;
  73.   }
  74.   if (j<strlen(wcs)) {             /* wildcard string not finished with */
  75.     for (;j<strlen(wcs);j++) {
  76.       if (wcs[j]!='*') return 0;   /* must be all *'s to match */
  77.     }
  78.     return 1; 
  79.   }
  80.   else return 1;
  81. }
  82. #else
  83.  
  84. /*
  85. **  Do shell-style pattern matching for ?, \, [], and * characters.
  86. **  Might not be robust in face of malformed patterns; e.g., "foo[a-"
  87. **  could cause a segmentation violation.  I think it's 8bit clean.
  88. **
  89. **  Written by Rich $alz, mirror!rs, Wed Nov 26 19:03:17 EST 1986.
  90. **  rsalz@bbn.com (Rich Salz)
  91. */
  92. /* Mods for ANSI compiler by  S.van Aardt (Mon 14, Jan 1991) */
  93.  
  94. extern int wildmat(register char *,register char *);
  95.  
  96. static int Star(register char *text, register char *p)
  97. {
  98.     while (!wildmat(text, p)) if (*++text == '\0') return FALSE;
  99.     return TRUE;
  100. }
  101.  
  102.  
  103. int wildmat(register char *text,register char *p)
  104. {
  105.     register int       last;
  106.     register int       matched;
  107.     register int       reverse;
  108.  
  109.     for ( ; *p; text++, p++)
  110.        switch (*p) {
  111.        case '\\':
  112.            /* Literal match with following character. */
  113.            p++;
  114.            /* FALLTHROUGH */
  115.        default:
  116.            if (tolower(*text) != tolower(*p)) /* SvA - "case-less" */
  117.              return FALSE;
  118.            continue;
  119.        case '?':
  120.            /* Match anything. */
  121.            if (*text == '\0')
  122.              return FALSE;
  123.            continue;
  124.        case '*':
  125.            /* Trailing star matches everything. */
  126.            return *++p ? Star(text, p) : TRUE;
  127.        case '[':
  128.            /* [^....] means inverse character class. */
  129.            if (reverse = p[1] == '^')
  130.              p++;
  131.            for (last = 0400, matched = FALSE; *++p && *p != ']'; last = *p)
  132.              /* This next line requires a good C compiler. */
  133.              if (*p == '-' ? *text <= *++p && *text >= last : *text == *p)
  134.                  matched = TRUE;
  135.            if (matched == reverse)
  136.              return FALSE;
  137.            continue;
  138.        }
  139.  
  140.     return *text == '\0';
  141. }
  142.  
  143. #endif
  144.  
  145.  
  146. /*-------------- search_index ----------------------------------------
  147.  * Purpoe     : searches an index page for matches with a (wildcarded)
  148.  *              string.
  149.  * Parameters : pointer to pathname of index page.
  150.  * Returns    : void
  151.  */
  152.  
  153. int search_index(char *pathname)
  154. {
  155.   FILE *fp=fopen(pathname,"r");
  156.   int  matches=0;
  157.   if (!fp)  {
  158.     fprintf(stderr,"Error: Couldn't open index page \"%s\"\n",pathname);
  159.     exit(1);
  160.   }
  161.   else {
  162.     while (!feof(fp))  {
  163.       char fname[40]={0},pname[80]={0},sink[132]={0};
  164.       fscanf(fp," %s %s",fname ,pname );
  165.       fgets(sink,132,fp);
  166.       if ( (wildmat("Name",fname)) && (wildmat("Appears",pname)) ) break;
  167.     }
  168.     while (!feof(fp))  {
  169.       char fname[40]={0},pname[40]={0},sink[132]={0};
  170.       fscanf(fp," %s %s",fname ,pname );
  171.       fgets(sink,132,fp);
  172.       if ( (fname[0]!=' ') && (wildmat(fname,keyword)) ) {
  173.         char *pg=NULL,*vol=NULL;
  174.         int i=0,j=0;
  175.         for (i=0; ((pname[i]) && (pname[i]!='(')); i++);
  176.         pg=calloc(sizeof(char),i+1);
  177.         strncpy(pg,pname,i);
  178.         for (j=++i; ((pname[i]) && (pname[i]!=')')); i++);
  179.         vol=calloc(sizeof(char),i-j+1);
  180.         strncpy(vol,(pname+j),i-j);
  181.         if (pg) {
  182.           const int pl=strlen(root_dir)+3+strlen(vol);
  183.           char *pathname;
  184.           pathname=calloc(sizeof(char),pl); 
  185.           strcpy(pathname,root_dir); /* current path */
  186.           strcat(pathname,".");  /* + directory name */
  187.           strcat(pathname,vol);
  188.           nk=1;
  189.           matches++;
  190.           vol_scan(pathname,pg);  /* recursive call into directory */
  191.           nk=0;
  192.           free(pathname);
  193.         }
  194.         free(vol);
  195.         free(pg);
  196.       }
  197.     }
  198.     fclose(fp);
  199.   }
  200.   return matches;
  201. }
  202.  
  203.  
  204. /*-------------- search_page -----------------------------------
  205.  * Purpoe     : searches a page for matches with a (wildcarded)
  206.  *              string.
  207.  * Parameters : pointer to pathname of page
  208.  * Returns    : void
  209.  */
  210.  
  211. void search_page(char *pathname)
  212. {
  213.   FILE *fp=fopen(pathname,"r");
  214.   long int i=0;
  215.   if (fp)
  216.   {
  217.     while (!feof(fp))    {
  218.       char *buffer=NULL;
  219.       int n=0,c=0;
  220.       i=ftell(fp);
  221.       for (n=0;((!feof(fp))&&((fgetc(fp))!='\n'));n++);
  222.       if (n) {
  223.         fseek(fp,(long) i,SEEK_SET);
  224.         buffer=calloc(sizeof(char),n+2);
  225.         for (n=0; ((!feof(fp))&&((c=fgetc(fp))!='\n')); n++)  {
  226.           if (!feof(fp)) buffer[n]=c; else buffer[n]='\0';
  227.         }
  228.       }
  229.       if (buffer)  {
  230.         int m=0;
  231.         char *p,*s="()[]'`~`@#$%^&*_-+={}\\|:;\"<>,.?/ ";
  232.         char *bfr;
  233.         bfr=calloc(sizeof(char),strlen(buffer)+1);
  234.         strcpy(bfr,buffer);
  235.         p=strtok(bfr,s); 
  236.         if (wildmat(p,search)) m=1;
  237.         while (p=strtok(NULL,s)) if (wildmat(p,search)) m=1;
  238.         if (m) fprintf(stderr,"%s : %s\n",pathname,buffer);
  239.         free(bfr);
  240.       }
  241.       free(buffer);
  242.     }
  243.     fclose(fp);
  244.   }
  245.   else {
  246.     fprintf(stderr,"Error: Couldn't open page \"%s\"\n",pathname);
  247.     exit(1);
  248.   }
  249. }
  250.  
  251.  
  252. /* -------------------------- vol_scan ---------------------------------
  253.  * Purpose    : tree-walks a directory sub-tree looking for matches
  254.  *              with the wildcard name (global).
  255.  * Parameters : pathname of directory to scan
  256.  * Returns    : void
  257.  */
  258.  
  259.  
  260. void vol_scan(const char *path,char *page)
  261. {
  262.  _kernel_swi_regs regs_in={0}, regs_out={0}; /* registers pre & post call */
  263.  _kernel_oserror *errnum;
  264.  int s=29+strlen(path)+11;   /* lengths of the file record + pathname string */
  265.  char *buffer;            
  266.  buffer=calloc(sizeof(char),s); /* allocate a buffer of suitable size */
  267.  regs_in.r[0]=11; /* Read file information from a specified directory */
  268.  regs_in.r[1]=(int) path; /* specified directory */
  269.  regs_in.r[2]=(int) buffer; /* destination data buffer */
  270.  regs_in.r[3]=1;    /* number of objects to read */
  271.  regs_in.r[4]=0;    /* offset of first item to be read */
  272.  regs_in.r[5]=s;    /* length of buffer */
  273.  regs_in.r[6]=0;    /* General wildcard '*' to get all */
  274.  do
  275.  {
  276.    errnum=_kernel_swi(0x0C, ®s_in, ®s_out);  /* SWI "OS_GBPB" */
  277.    if (!errnum) /* ie if no errors */
  278.    {
  279.      if (regs_out.r[3]==1) /* ie if something read */
  280.      {
  281.        if (((int) *(buffer+16))==2) /* object is a directory */
  282.        { /* make a string containg the full pathname now */
  283.          const int pl=strlen(path)+3+strlen((buffer+29));
  284.          char *pathname;
  285.          pathname=calloc(sizeof(char),pl); 
  286.          strcpy(pathname,path); /* current path */
  287.          strcat(pathname,".");  /* + directory name */
  288.          strcat(pathname,(buffer+29));
  289.          vol_scan(pathname,page);  /* recursive call into directory */
  290.          free(pathname);
  291.        }
  292.        else
  293.        {
  294.          char *name;
  295.          name=(buffer+29);
  296.          if ((nk) || (!keyword))
  297.          {
  298.            if (wildmat(name,page)) /* page filename matches search page ? */
  299.            {
  300.              found=1;
  301.              if (!index)
  302.              {
  303.                /* create full pathname & if required tag to display command */
  304.                const int pl=strlen(com)+strlen(path)+4+strlen((buffer+29));
  305.                char *pathname;
  306.                int  err;
  307.                pathname=calloc(sizeof(char),pl); 
  308.                if (!search)
  309.                { 
  310.                  strcpy(pathname,com);
  311.                  strcat(pathname," ");
  312.                  strcat(pathname,path);
  313.                }
  314.                else strcpy(pathname,path);                
  315.                strcat(pathname,".");  /* + directory name */
  316.                strcat(pathname,(buffer+29));
  317.      
  318.                if (!search)
  319.                {
  320.                  err=_kernel_system(pathname,0);
  321.                  if (err)
  322.                  {
  323.                    fprintf(stderr,"\n\n");
  324.                    exit(1);
  325.                  }
  326.                }
  327.                else search_page(pathname);
  328.              } 
  329.              else
  330.              {
  331.                fprintf(stdout,"Volume %s ",(path+strlen(root_dir)+1));
  332.                fprintf(stdout,"Page %s\n",(buffer+29) );
  333.              }
  334.            }
  335.          }
  336.          else
  337.          {
  338.            if ((wildmat(name,"list"))) /* filename matches list page ? */
  339.            {
  340.              const int pl=strlen(path)+3+strlen((buffer+29));
  341.              char *pathname;
  342.              int matches=0;
  343.              pathname=calloc(sizeof(char),pl); 
  344.              strcpy(pathname,path); /* current path */
  345.              strcat(pathname,".");  /* + directory name */
  346.              strcat(pathname,(buffer+29));
  347.              matches=search_index(pathname);
  348.              free(pathname);
  349.            }
  350.          }
  351.        }
  352.        regs_in.r[4]=regs_out.r[4]; /* offset of next item to read */
  353.      }
  354.    }
  355.    else  {
  356.      if (!nk) fprintf(stderr,"Error : Manual path \"%s\" not found\n",path);
  357.        break;
  358.    }
  359.  }
  360.  while ((regs_out.r[4]!=-1)&&(regs_out.r[3]==1));
  361.  free(buffer);
  362. }
  363.  
  364. /*-------------------- escape ---------------------------------------
  365.  * Purpose    : handles signal interrupts, exits from the program
  366.  * Parameters : signal code
  367.  * Returns    : void
  368.  */
  369. void escape(int sig)
  370. {
  371.   if (sig!=4) {
  372.     fprintf(stderr,"Aborted by Interrupt %d\n",sig);
  373.   } else fprintf(stderr,"\n");
  374.   exit(1);
  375. }
  376.  
  377. /*-------------------- syntax --------------------------*
  378.  * Purpose    : Displays syntax message about program
  379.  * Parameters : pointer to program name (argv[0])
  380.  * Returns    : void
  381.  *------------------------------------------------------*/
  382. void syntax_message(const char *prog_name)
  383. {
  384.   char *syntax="[section] [title] [-k keyword] [-s string] [-i]";
  385.   fprintf(stderr,"usage:   %s %s\n",prog_name,syntax);
  386.   fprintf(stderr,"author:  S. van Aardt\n");
  387.   fprintf(stderr,"version: %s (%s)\n", version, __DATE__);
  388.   fprintf(stderr,"         section   Search within manual section #\n");
  389.   fprintf(stderr,"         title     Page to search for\n");
  390.   fprintf(stderr,"         -k        Search page lists for keyword\n");
  391.   fprintf(stderr,"         -i        Display pages available\n");
  392.   fprintf(stderr,"         -s        Search through pages for word\n");
  393.   fprintf(stderr,"Note:    wildcards are available in searches\n");
  394.   exit(1);
  395. }
  396.   
  397.  
  398. /*-------------------- read_sys_var ---------------------------*
  399.  * Purpose    : Obtain the value of a system variable.
  400.  * Arguments  : pointer to name of system variable to be read.
  401.  * Returns    : pointer to value read.
  402.  *-------------------------------------------------------------*/
  403.  
  404. char *read_sys_var(const char *variable)
  405. {
  406.   _kernel_swi_regs pre={0}, post={0}; /* registers pre & post call */
  407.   _kernel_oserror *errnum;
  408.   char *buffer=calloc(sizeof(char),255);
  409.   pre.r[0]=(int) variable;
  410.   pre.r[1]=(int) buffer;
  411.   pre.r[2]=255;
  412.   pre.r[3]=0;
  413.   pre.r[4]=3;
  414.   errnum=_kernel_swi(0x23, &pre, &post);  /* SWI "OS_ReadVarVal" */
  415.   if (!errnum) {
  416.     return buffer;
  417.   } else {
  418.    free(buffer);
  419.    return NULL;
  420.   }
  421. }                                       
  422.  
  423.  
  424. int main(int argc,char *argv[])
  425. {
  426.   int c=0,okay=1,rf=1;
  427.   extern char *optarg;
  428.   extern int  optind;
  429.   extern int  getopt(int argc,char **argv, char *optstring);
  430.  
  431.   signal(SIGINT, escape);  /* When interrupted by Escape call 'escape' */
  432.  
  433.   root_dir=read_sys_var("man$path"); /* where to find manual pages */
  434.   if (!root_dir) {
  435.     root_dir="$.usr.man"; /* use this if no man$path */
  436.     rf=0;       /* & note that I can't free root_dir now */
  437.   }
  438.   com=read_sys_var("man$com"); /* describes command for displaying pages */
  439.   if (!com) com="TYPE "; 
  440.   /* Parse command line arguments */
  441.   while ((c = getopt(argc,argv,"ik:s:?")) != -1) {
  442.     switch (c)    {
  443.     case 'k' : /* keyword search through indexes */
  444.                keyword=optarg; 
  445.                break;
  446.     case 's' : /* word search through each page */
  447.                search=optarg;
  448.                break;
  449.     case 'i' : /* produce index of page names */
  450.                index=1;
  451.                break;
  452.     case '?' : /* produce syntax message */
  453.                okay=0;
  454.                break;
  455.     }
  456.   }
  457.   if (okay)  {
  458.     if (optind<argc) { /* if more arguments are left to parse */
  459.       int i=optind;
  460.       for (i=optind; i<argc; i++) {
  461.         char *p=argv[i],c=p[0];
  462.         if isdigit(c) { /* then assume referring to manual volume  */
  463.           if (!volume) volume=p; 
  464.           else {
  465.             fprintf(stderr,"invalid arguments\n");
  466.             syntax_message(argv[0]);
  467.             break;
  468.           }
  469.         } 
  470.         else {
  471.           if (!page) page=p;
  472.           else {
  473.             fprintf(stderr,"Argument error\n");
  474.             syntax_message(argv[0]);
  475.             break;
  476.           }
  477.         }
  478.       }
  479.     }
  480.     if ((!volume) && (!page) && (!keyword) && (!search) && (!index)) 
  481.       syntax_message(argv[0]);
  482.     if ((!page) && (!keyword) && (!search) && (!index)) {
  483.       fprintf(stderr,"Error no page given\n");
  484.       syntax_message(argv[0]);
  485.     }
  486.     if (!page) page="*";
  487.     if (volume) {
  488.       const int pl=strlen(root_dir)+3+strlen(volume);
  489.       char *pathname;
  490.       pathname=calloc(sizeof(char),pl); 
  491.       strcpy(pathname,root_dir); /* current path */
  492.       strcat(pathname,".");  /* + directory name */
  493.       strcat(pathname,volume);
  494.       vol_scan(pathname,page);  /* search through a specific manual volume */
  495.       free(pathname);
  496.     }
  497.     else vol_scan(root_dir,page); /* go through all manual volumes */
  498.    if (!found)  fprintf(stderr,"Manual page %s not found\n",page);
  499.   } else syntax_message(argv[0]);
  500.   if ((root_dir)&&(rf)) free(root_dir);
  501.   if (com) free(com);
  502.   return 0;
  503. }
  504.  
  505.